﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.SessionState;
using hlib.IO;
using SalesSys.Comm.BLL;
using SalesSys.Comm.Utility;
using SalesSys.WebCore;
using SalesSys.WebCore.Authorize;

namespace SalesSys.Site.Controllers.Api
{
    public static class BaseWebApiEx
    {
        /// <summary>
        /// 获取所有键值
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static NameValueCollection GetQueryStrings(this HttpRequestMessage request)
        {
            NameValueCollection nv=new NameValueCollection();
          
            var list=request.GetQueryNameValuePairs();
            foreach (var item in list)
            {
                nv.Add(item.Key,item.Value);
            }
            return nv;
        }
        /// <summary>
        /// 获取单个键值
        /// </summary>
        /// <param name="request"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetQueryString(this HttpRequestMessage request, string key)
        {
            var queryStrings = request.GetQueryNameValuePairs();
            if (queryStrings == null)
                return null;

            var match = queryStrings.FirstOrDefault(kv => string.Compare(kv.Key, key, true) == 0);
            if (string.IsNullOrEmpty(match.Value))
                return null;

            return match.Value;
        }
        /// <summary>
        /// 依据键获取请求头中值数据
        /// </summary>
        /// <param name="request"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetHeader(this HttpRequestMessage request, string key)
        {
            IEnumerable<string> keys = null;
            if (!request.Headers.TryGetValues(key, out keys))
                return null;

            return keys.First();
        }
        /// <summary>
        /// 获取Cookie
        /// </summary>
        /// <param name="request"></param>
        /// <param name="cookieName"></param>
        /// <returns></returns>
        public static string GetCookie(this HttpRequestMessage request, string cookieName)
        {
            CookieHeaderValue cookie = request.Headers.GetCookies(cookieName).FirstOrDefault();
            if (cookie != null)
                return cookie[cookieName].Value;

            return null;
        }
    }

    [ApiUserRoleAuth]
    [WebApiExceptionFilter]
    public abstract class BaseApiController : ApiController
    {
        private ContextSession session;
        /// <summary>
        /// 会话数据
        /// </summary>
        protected internal ContextSession Session
        {
            get { return session ?? new ContextSession(); } 
        }

       internal protected ISimplePagingInfo GetRequestQuery()
        {
          
            QueryInfo q = new QueryInfo();
            var form=Request.GetQueryStrings();
           var nform = new NameValueCollection();
          
            q.Page = NumEx.ToIntOrDefault(form["page"], SiteConfig.ConfigInfo.PageNum);
            q.Rows = NumEx.ToIntOrDefault(form["rows"], SiteConfig.ConfigInfo.PageSize);
            q.OrderFirst = form["sort"];
            q.IsDescFirst = form["order"] == "desc";
            return q;
        }

        /// <summary>
        /// 获取当前请求上传的文件
        /// </summary>
       /// <returns>上传文件的信息，默认会重命名</returns>
        internal MultipartFormDataStreamProvider GetFiles(string path="file")
        {
            if (!Request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
            }
            string root = HttpContext.Current.Server.MapPath("~/"+path); //指定要将文件存入的服务器物理位置  
            if (!Directory.Exists(root))
            {
                Directory.CreateDirectory(root);
            }
            var provider =   RenamingMultipartFormDataStreamProvider.CreateTimeFileName(root );
          
            Request.Content.ReadAsMultipartAsync(provider);
            return provider;
        }

        public static  HttpResponseMessage CreateStreamResponse(Stream stream, string name, bool isShow, string mediaType = null)
       {
          
           string customFileName = name;//客户端保存的文件名  

           // FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            HttpResponseMessage response = new HttpResponseMessage();
            response.Content = new StreamContent(stream);
            var contentDisposition = isShow ? "Inline" : "attachment";
            if (mediaType==null)
            {
                var ext=Path.GetExtension(customFileName);
               mediaType= GetMediaType(ext);

            }
            response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue(contentDisposition);
            response.Content.Headers.ContentDisposition.FileName = customFileName;
            response.Content.Headers.ContentType = new MediaTypeHeaderValue(mediaType);  
           
            //response.Content.Headers.ContentLength = new FileInfo(filePath).Length;
           //
            //Image img = GetImage(imageName, width, height);
            //using (MemoryStream ms = new MemoryStream())
            //{
            //    img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
            //    HttpResponseMessage result = new HttpResponseMessage();
            //    result.Content = new ByteArrayContent(ms.ToArray());
            //    result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
            //    return result;
            //}

            return response; 
        }

        public static HttpResponseMessage CsvExp(string fileName,IEnumerable<IEnumerable<string>> expData, string[] nameArray=null)
        {
            MemoryStream sm = new MemoryStream();
            StreamWriter sw = new StreamWriter(sm, Encoding.Default);

            new CsvWriter(sw).WriteAllLines(expData, nameArray);
            sm.Position = 0;
            var msg = CreateStreamResponse(sm, fileName, false);
            return msg;
        }

        public static string GetMediaType(string extName)
        {
            switch (extName)
            {
                case "png":
                    return "image/png";
                case "jpg":
                    return "image/jpg";
                default:
                    return "application/octet-stream";// 这句话要告诉浏览器要下载文件  
            }
        }

        protected  internal class ContextSession 
        {
            internal ContextSession()
            {
            }

            private HttpSessionState WebSession
            {
                get { return System.Web.HttpContext.Current.Session; }
            }

            public object this[string key]
            {
                get { return WebSession[key]; }
                set { WebSession[key] = value; }
            }
        }
    }
    public class RenamingMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
    {
 
        public Func<string , string> SetFileName { get; private set; }

        public static RenamingMultipartFormDataStreamProvider CreateTimeFileName(string root)
        {
            var fun = new Func<string, string>(p =>
            {
                var extension = Path.GetExtension(p);
                var name = DateTime.Now.ToString("yyyyMMddHHmmssffff") + new Random().Next(1000,9999);

               return name + extension;
            });
            return new RenamingMultipartFormDataStreamProvider(root, fun);

        }

        public static RenamingMultipartFormDataStreamProvider CreateGuidFileName(string root)
        {
            var fun = new Func<string, string>(p =>
            {
                var extension = Path.GetExtension(p);
                var name = Guid.NewGuid().ToString("N");
                return name + extension;
            });
            return new RenamingMultipartFormDataStreamProvider(root,fun);
             
        }

        public RenamingMultipartFormDataStreamProvider(string root, Func<string , string>  setLocalFileName=null)
            : base(root)
        {
            SetFileName = setLocalFileName;
        }

        public override string GetLocalFileName(HttpContentHeaders headers)
        {
            if (SetFileName == null)
            {
                return base.GetLocalFileName(headers);
            }
            string filePath = headers.ContentDisposition.FileName;
            // Multipart requests with the file name seem to always include quotes.
            if (filePath.StartsWith(@"""") && filePath.EndsWith(@""""))
                filePath = filePath.Substring(1, filePath.Length - 2);

            var filename = Path.GetFileName(filePath);
            filename = SetFileName(filename);
            filename = Path.Combine(RootPath, filename);
            return filename;
        }

    }
    public class ApiArgException : ArgumentException
    {
        public ApiArgException() { }
        public ApiArgException(string message) : base(message) { }


        public ApiArgException(string message, string paramName) : base(message, paramName) { }

    }
    //AuthorizeAttribute
    /// <summary>
    /// 用户角色标记,使用WXRoleDataSign定义,只要有给定角色就可以访问，宽松验证，不给定标识只要登录即可
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class ApiUserRoleAuthAttribute : AuthorizeAttribute
    {
        public string[] RoleList { get; set; }
        public string RedirectUrl { get; set; }
        /// <summary>
        /// 允许的角色名列表
        /// </summary>
        /// <param name="roles">允许的角色名列表，为null允许任何已登录用户访问</param>
        public ApiUserRoleAuthAttribute(params string[] roles)
        {
            
            RoleList = roles;
        }
        //protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
        //{
        //    if (RoleList == null || RoleList.Length < 1)
        //    {
        //        return httpContext.User != null && httpContext.User.Identity != null && httpContext.User.Identity.IsAuthenticated && ClientHelper.ClientInfo != null;
        //    }
        //    return RoleList.Any(ClientHelper.IsHaveRole);
        //    //   FormsAuthentication
        //    //return base.AuthorizeCore(httpContext);
        //}
        //protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        //{
        //    if (RedirectUrl != null)
        //    {
        //        var url = filterContext.HttpContext.Request.RawUrl;
        //        filterContext.Result = new RedirectResult(RedirectUrl + "?ReturnUrl=" + HttpUtility.UrlEncode(url), false);
        //        return;
        //    }
        //    base.HandleUnauthorizedRequest(filterContext);
        //    string url1 = "~/Home/Index";
        //    filterContext.Result = new RedirectResult(url1);

        //}
        protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
        {
            base.HandleUnauthorizedRequest(actionContext);  
        }

        public override void OnAuthorization(HttpActionContext actionContext)
        {
            base.OnAuthorization(actionContext);

            string authParameter = null;
            
            var authValue = actionContext.Request.Headers.Authorization;
            if (authValue != null && authValue.Scheme == "Token")
                authParameter = authValue.Parameter;

            if (string.IsNullOrEmpty(authParameter))
                return;

        }

        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            if (RoleList == null || RoleList.Length < 1)
            {
                return  ClientHelper.ClientInfo != null;
            }
            return RoleList.Any(ClientHelper.IsHaveRole);
           // return base.IsAuthorized(actionContext);
        }
    }
}